package com.daffodil.core.service.impl;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.daffodil.core.dao.JpaDao;
import com.daffodil.core.entity.BaseEntity;
import com.daffodil.core.entity.Query;
import com.daffodil.core.service.IBaseEntityService;
import com.daffodil.util.HqlUtils;
import com.daffodil.util.StringUtils;

/**
 * 基础实体对象实现类默认实现增删改查
 * @author yweijian
 * @date 2023年1月31日
 * @version 2.0.0
 * @description
 */
public class BaseEntityServiceImpl<ID, T> implements IBaseEntityService<ID, T> {

    @Autowired
    public JpaDao<ID> jpaDao;

    @SuppressWarnings("unchecked")
    protected Class<T> getTClass() {
        ParameterizedType type = this.tryGetParameterizedType(this.getClass().getGenericSuperclass());
        try {
            Type[] args = type.getActualTypeArguments();
            return (Class<T>) args[1];
        }catch (Exception e) {
            throw new IllegalArgumentException("Try to get Class actual type arguments is null");
        }
    }

    @SuppressWarnings("unchecked")
    protected ParameterizedType tryGetParameterizedType(Type type) {
        if(type == null) {
            return null;
        }
        if(type instanceof ParameterizedType) {
            Type[] args = ((ParameterizedType) type).getActualTypeArguments();
            if(args != null && args.length == 2) {
                if(args[1] != null && args[1] instanceof BaseEntity) {
                    return (ParameterizedType) type;
                }
            }
        }
        return this.tryGetParameterizedType(((Class<T>) type).getGenericSuperclass());
    }

    @Override
    public List<T> selectEntityList(Query<T> query) {
        StringBuffer hql = new StringBuffer(StringUtils.format("from {} where 1=1 ", this.getTClass().getName()));
        List<Object> paras = new ArrayList<Object>();
        HqlUtils.createHql(hql, paras, query);
        return jpaDao.search(hql.toString(), paras, this.getTClass(), query.getPage());
    }

    @Override
    public T selectEntityById(ID id) {
        return jpaDao.find(this.getTClass(), id);
    }

    @Override
    @Transactional
    public void deleteEntityByIds(ID[] ids) {
        jpaDao.delete(this.getTClass(), ids);
    }

    @Override
    @Transactional
    @SuppressWarnings("unchecked")
    public void insertEntity(T entity) {
        jpaDao.save((BaseEntity<ID>) entity);
    }

    @Override
    @Transactional
    @SuppressWarnings("unchecked")
    public void updateEntity(T entity) {
        jpaDao.update((BaseEntity<ID>) entity);
    }
}
